/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant;
import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.tools.ant.taskdefs.condition.Os;
import org.junit.Before;
import org.junit.ComparisonFailure;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* JUnit testcases for org.apache.tools.ant.IntrospectionHelper.
*
*/
public class IntrospectionHelperTest {
private Project p;
private IntrospectionHelper ih;
private static final String projectBasedir = File.separator;
@Before
public void setUp() {
p = new Project();
p.setBasedir(projectBasedir);
ih = IntrospectionHelper.getHelper(getClass());
}
@Test
public void testIsDynamic() {
assertFalse("Not dynamic", ih.isDynamic());
}
@Test
public void testIsContainer() {
assertFalse("Not a container", ih.isContainer());
}
@Test
public void testAddText() throws BuildException {
ih.addText(p, this, "test");
try {
ih.addText(p, this, "test2");
fail("test2 shouldn\'t be equal to test");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof ComparisonFailure);
}
ih = IntrospectionHelper.getHelper(String.class);
try {
ih.addText(p, "", "test");
fail("String doesn\'t support addText");
} catch (BuildException be) {
//TODO the value should be asserted
}
}
@Test
@Ignore("This silently ignores a build exception")
public void testGetAddTextMethod() {
Method m = ih.getAddTextMethod();
assertMethod(m, "addText", String.class, "test", "bing!");
ih = IntrospectionHelper.getHelper(String.class);
try {
m = ih.getAddTextMethod();
} catch (BuildException e) {}
}
@Test
public void testSupportsCharacters() {
assertTrue("IntrospectionHelperTest supports addText",
ih.supportsCharacters());
ih = IntrospectionHelper.getHelper(String.class);
assertTrue("String doesn\'t support addText", !ih.supportsCharacters());
}
public void addText(String text) {
assertEquals("test", text);
}
@Test
public void testElementCreators() throws BuildException {
try {
ih.getElementType("one");
fail("don't have element type one");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("two");
fail("createTwo takes arguments");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("three");
fail("createThree returns void");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("four");
fail("createFour returns array");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("five");
fail("createFive returns primitive type");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
assertEquals(String.class, ih.getElementType("six"));
assertEquals("test", ih.createElement(p, this, "six"));
try {
ih.getElementType("seven");
fail("addSeven takes two arguments");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("eight");
fail("addEight takes no arguments");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("nine");
fail("nine return non void");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("ten");
fail("addTen takes array argument");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("eleven");
fail("addEleven takes primitive argument");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.getElementType("twelve");
fail("no primitive constructor for java.lang.Class");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
assertEquals(StringBuffer.class, ih.getElementType("thirteen"));
assertEquals("test", ih.createElement(p, this, "thirteen").toString());
try {
ih.createElement(p, this, "fourteen");
fail("fourteen throws NullPointerException");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof NullPointerException);
}
try {
ih.createElement(p, this, "fourteen");
fail("fifteen throws NullPointerException");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof NullPointerException);
}
}
private Map getExpectedNestedElements() {
Map elemMap = new Hashtable();
elemMap.put("six", String.class);
elemMap.put("thirteen", StringBuffer.class);
elemMap.put("fourteen", StringBuffer.class);
elemMap.put("fifteen", StringBuffer.class);
return elemMap;
}
@Test
public void testGetNestedElements() {
Map elemMap = getExpectedNestedElements();
Enumeration e = ih.getNestedElements();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
Class expect = (Class) elemMap.get(name);
assertNotNull("Support for "+name+" in IntrospectioNHelperTest?",
expect);
assertEquals("Return type of "+name, expect, ih.getElementType(name));
elemMap.remove(name);
}
assertTrue("Found all", elemMap.isEmpty());
}
@Test
public void testGetNestedElementMap() {
Map elemMap = getExpectedNestedElements();
Map actualMap = ih.getNestedElementMap();
for (Iterator i = actualMap.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
String elemName = (String) entry.getKey();
Class elemClass = (Class) elemMap.get(elemName);
assertNotNull("Support for " + elemName +
" in IntrospectionHelperTest?", elemClass);
assertEquals("Type of " + elemName, elemClass, entry.getValue());
elemMap.remove(elemName);
}
assertTrue("Found all", elemMap.isEmpty());
// Check it's a read-only map.
try {
actualMap.clear();
//TODO we should be asserting a value somewhere in here
} catch (UnsupportedOperationException e) {}
}
@Test
public void testGetElementMethod() {
assertElemMethod("six", "createSix", String.class, null);
assertElemMethod("thirteen", "addThirteen", null, StringBuffer.class);
assertElemMethod("fourteen", "addFourteen", null, StringBuffer.class);
assertElemMethod("fifteen", "createFifteen", StringBuffer.class, null);
}
private void assertElemMethod(String elemName, String methodName,
Class returnType, Class methodArg) {
Method m = ih.getElementMethod(elemName);
assertEquals("Method name", methodName, m.getName());
Class expectedReturnType = (returnType == null)? Void.TYPE: returnType;
assertEquals("Return type", expectedReturnType, m.getReturnType());
Class[] args = m.getParameterTypes();
if (methodArg != null) {
assertEquals("Arg Count", 1, args.length);
assertEquals("Arg Type", methodArg, args[0]);
} else {
assertEquals("Arg Count", 0, args.length);
}
}
public Object createTwo(String s) {
return null;
}
public void createThree() {}
public Object[] createFour() {
return null;
}
public int createFive() {
return 0;
}
public String createSix() {
return "test";
}
public StringBuffer createFifteen() {
throw new NullPointerException();
}
public void addSeven(String s, String s2) {}
public void addEight() {}
public String addNine(String s) {
return null;
}
public void addTen(String[] s) {}
public void addEleven(int i) {}
public void addTwelve(Class c) {}
public void addThirteen(StringBuffer sb) {
sb.append("test");
}
public void addFourteen(StringBuffer s) {
throw new NullPointerException();
}
@Test
public void testAttributeSetters() throws BuildException {
try {
ih.setAttribute(p, this, "one", "test");
fail("setOne doesn't exist");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.setAttribute(p, this, "two", "test");
fail("setTwo returns non void");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.setAttribute(p, this, "three", "test");
fail("setThree takes no args");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.setAttribute(p, this, "four", "test");
fail("setFour takes two args");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.setAttribute(p, this, "five", "test");
fail("setFive takes array arg");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
try {
ih.setAttribute(p, this, "six", "test");
fail("Project doesn't have a String constructor");
} catch (BuildException be) {
//TODO we should be asserting a value in here
}
ih.setAttribute(p, this, "seven", "2");
try {
ih.setAttribute(p, this, "seven", "3");
fail("2 shouldn't be equals to three");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof ComparisonFailure);
}
ih.setAttribute(p, this, "eight", "2");
try {
ih.setAttribute(p, this, "eight", "3");
fail("2 shouldn't be equals to three - as int");
} catch (BuildException be) {
assertTrue("Cause of error: " + be.toString(), be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "nine", "2");
try {
ih.setAttribute(p, this, "nine", "3");
fail("2 shouldn't be equals to three - as Integer");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "ten", "2");
try {
ih.setAttribute(p, this, "ten", "3");
fail(projectBasedir+"2 shouldn't be equals to "+projectBasedir+"3");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "eleven", "2");
try {
ih.setAttribute(p, this, "eleven", "on");
fail("on shouldn't be false");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "twelve", "2");
try {
ih.setAttribute(p, this, "twelve", "on");
fail("on shouldn't be false");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.Project");
try {
ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.ProjectHelper");
fail("org.apache.tools.ant.Project shouldn't be equal to org.apache.tools.ant.ProjectHelper");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
try {
ih.setAttribute(p, this, "thirteen", "org.apache.tools.ant.Project2");
fail("org.apache.tools.ant.Project2 doesn't exist");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof ClassNotFoundException);
}
ih.setAttribute(p, this, "fourteen", "2");
try {
ih.setAttribute(p, this, "fourteen", "on");
fail("2 shouldn't be equals to three - as StringBuffer");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof ComparisonFailure);
}
ih.setAttribute(p, this, "fifteen", "abcd");
try {
ih.setAttribute(p, this, "fifteen", "on");
fail("o shouldn't be equal to a");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "sixteen", "abcd");
try {
ih.setAttribute(p, this, "sixteen", "on");
fail("o shouldn't be equal to a");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "seventeen", "17");
try {
ih.setAttribute(p, this, "seventeen", "3");
fail("17 shouldn't be equals to three");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "eightteen", "18");
try {
ih.setAttribute(p, this, "eightteen", "3");
fail("18 shouldn't be equals to three");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
ih.setAttribute(p, this, "nineteen", "19");
try {
ih.setAttribute(p, this, "nineteen", "3");
fail("19 shouldn't be equals to three");
} catch (BuildException be) {
assertTrue(be.getCause() instanceof AssertionError);
}
}
private Map getExpectedAttributes() {
Map attrMap = new Hashtable();
attrMap.put("seven", String.class);
attrMap.put("eight", Integer.TYPE);
attrMap.put("nine", Integer.class);
attrMap.put("ten", File.class);
attrMap.put("eleven", Boolean.TYPE);
attrMap.put("twelve", Boolean.class);
attrMap.put("thirteen", Class.class);
attrMap.put("fourteen", StringBuffer.class);
attrMap.put("fifteen", Character.TYPE);
attrMap.put("sixteen", Character.class);
attrMap.put("seventeen", Byte.TYPE);
attrMap.put("eightteen", Short.TYPE);
attrMap.put("nineteen", Double.TYPE);
attrMap.put("twenty", Path.class);
/*
* JUnit 3.7 adds a getName method to TestCase - so we now
* have a name attribute in IntrospectionHelperTest if we run
* under JUnit 3.7 but not in earlier versions.
*
* Simply add it here and remove it after the tests.
*/
attrMap.put("name", String.class);
return attrMap;
}
@Test
public void testGetAttributes() {
Map attrMap = getExpectedAttributes();
Enumeration e = ih.getAttributes();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
Class expect = (Class) attrMap.get(name);
assertNotNull("Support for "+name+" in IntrospectionHelperTest?",
expect);
assertEquals("Type of "+name, expect, ih.getAttributeType(name));
attrMap.remove(name);
}
attrMap.remove("name");
assertTrue("Found all", attrMap.isEmpty());
}
@Test
public void testGetAttributeMap() {
Map attrMap = getExpectedAttributes();
Map actualMap = ih.getAttributeMap();
for (Iterator i = actualMap.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
String attrName = (String) entry.getKey();
Class attrClass = (Class) attrMap.get(attrName);
assertNotNull("Support for " + attrName +
" in IntrospectionHelperTest?", attrClass);
assertEquals("Type of " + attrName, attrClass, entry.getValue());
attrMap.remove(attrName);
}
attrMap.remove("name");
assertTrue("Found all", attrMap.isEmpty());
// Check it's a read-only map.
try {
actualMap.clear();
//TODO we should be asserting a value somewhere in here
} catch (UnsupportedOperationException e) {}
}
@Test
public void testGetAttributeMethod() {
assertAttrMethod("seven", "setSeven", String.class,
"2", "3");
assertAttrMethod("eight", "setEight", Integer.TYPE,
new Integer(2), new Integer(3));
assertAttrMethod("nine", "setNine", Integer.class,
new Integer(2), new Integer(3));
assertAttrMethod("ten", "setTen", File.class,
new File(projectBasedir + 2), new File("toto"));
assertAttrMethod("eleven", "setEleven", Boolean.TYPE,
Boolean.FALSE, Boolean.TRUE);
assertAttrMethod("twelve", "setTwelve", Boolean.class,
Boolean.FALSE, Boolean.TRUE);
assertAttrMethod("thirteen", "setThirteen", Class.class,
Project.class, Map.class);
assertAttrMethod("fourteen", "setFourteen", StringBuffer.class,
new StringBuffer("2"), new StringBuffer("3"));
assertAttrMethod("fifteen", "setFifteen", Character.TYPE,
new Character('a'), new Character('b'));
assertAttrMethod("sixteen", "setSixteen", Character.class,
new Character('a'), new Character('b'));
assertAttrMethod("seventeen", "setSeventeen", Byte.TYPE,
new Byte((byte)17), new Byte((byte)10));
assertAttrMethod("eightteen", "setEightteen", Short.TYPE,
new Short((short)18), new Short((short)10));
assertAttrMethod("nineteen", "setNineteen", Double.TYPE,
new Double(19), new Double((short)10));
assertAttrMethod("twenty", "setTwenty", Path.class,
new File(projectBasedir + 20).toPath(), Paths.get("toto"));
try {
assertAttrMethod("onehundred", null, null, null, null);
fail("Should have raised a BuildException!");
} catch (BuildException e) {
//TODO we should be asserting a value in here
}
}
private void assertAttrMethod(String attrName, String methodName,
Class methodArg, Object arg, Object badArg) {
Method m = ih.getAttributeMethod(attrName);
assertMethod(m, methodName, methodArg, arg, badArg);
}
public int setTwo(String s) {
return 0;
}
public void setThree() {}
public void setFour(String s1, String s2) {}
public void setFive(String[] s) {}
public void setSix(Project p) {}
public void setSeven(String s) {
assertEquals("2", s);
}
public void setEight(int i) {
assertEquals(2, i);
}
public void setNine(Integer i) {
assertEquals(2, i.intValue());
}
public void setTen(File f) {
String path = f.getAbsolutePath();
if (Os.isFamily("unix") || Os.isFamily("openvms")) {
assertEquals(projectBasedir+"2", path);
} else if (Os.isFamily("netware")) {
assertEquals(projectBasedir+"2", path.toLowerCase(Locale.US));
} else {
assertEquals(":"+projectBasedir+"2",
path.toLowerCase(Locale.US).substring(1));
}
}
public void setEleven(boolean b) {
assertTrue(!b);
}
public void setTwelve(Boolean b) {
assertTrue(!b.booleanValue());
}
public void setThirteen(Class c) {
assertEquals(Project.class, c);
}
public void setFourteen(StringBuffer sb) {
assertEquals("2", sb.toString());
}
public void setFifteen(char c) {
assertEquals(c, 'a');
}
public void setSixteen(Character c) {
assertEquals(c.charValue(), 'a');
}
public void setSeventeen(byte b) {
assertEquals(17, b);
}
public void setEightteen(short s) {
assertEquals(18, s);
}
public void setNineteen(double d) {
double diff = d - 19;
assertTrue("Expected 19, received " + d, diff > -1e-6 && diff < 1e-6);
}
public void setTwenty(Path p) {
String path = p.toAbsolutePath().toString();
if (Os.isFamily("unix") || Os.isFamily("openvms")) {
assertEquals(projectBasedir+"20", path);
} else if (Os.isFamily("netware")) {
assertEquals(projectBasedir+"20", path.toLowerCase(Locale.US));
} else {
assertEquals(":"+projectBasedir+"20",
path.toLowerCase(Locale.US).substring(1));
}
}
@Test
public void testGetExtensionPoints() {
List extensions = ih.getExtensionPoints();
final int adders = 2;
assertEquals("extension count", adders, extensions.size());
// this original test assumed something about the order of
// add(Number) and addConfigured(Map) returned by reflection.
// Unfortunately the assumption doesn't hold for all VMs
// (failed on MacOS X using JDK 1.4.2_05) and the possible
// combinatorics are too hard to check. We really only want
// to ensure that the more derived Hashtable can be found
// before Map.
// assertExtMethod(extensions.get(0), "add", Number.class,
// new Integer(2), new Integer(3));
// addConfigured(Hashtable) should come before addConfigured(Map)
assertExtMethod(extensions.get(adders - 2),
"addConfigured", Hashtable.class,
makeTable("key", "value"), makeTable("1", "2"));
assertExtMethod(extensions.get(adders - 1), "addConfigured", Map.class,
new HashMap(), makeTable("1", "2"));
}
private void assertExtMethod(Object mo, String methodName, Class methodArg,
Object arg, Object badArg) {
assertMethod((Method) mo, methodName, methodArg, arg, badArg);
}
private void assertMethod(Method m, String methodName, Class methodArg,
Object arg, Object badArg) {
assertEquals("Method name", methodName, m.getName());
assertEquals("Return type", Void.TYPE, m.getReturnType());
Class[] args = m.getParameterTypes();
assertEquals("Arg Count", 1, args.length);
assertEquals("Arg Type", methodArg, args[0]);
try {
m.invoke(this, new Object[] { arg });
} catch (IllegalAccessException e) {
throw new BuildException(e);
} catch (InvocationTargetException e) {
throw new BuildException(e);
}
try {
m.invoke(this, new Object[] { badArg });
fail("Should have raised an assertion exception");
} catch (IllegalAccessException e) {
throw new BuildException(e);
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
assertTrue(t.toString(), t instanceof AssertionError);
}
}
public List add(List l) {
// INVALID extension point
return null;
}
// see comments in testGetExtensionPoints
// public void add(Number n) {
// // Valid extension point
// assertEquals(2, n.intValue());
// }
public void add(List l, int i) {
// INVALID extension point
}
public void addConfigured(Map m) {
// Valid extension point
assertTrue(m.size() == 0);
}
public void addConfigured(Hashtable h) {
// Valid extension point, more derived than Map above, but *after* it!
assertEquals(makeTable("key", "value"), h);
}
private Hashtable makeTable(Object key, Object value) {
Hashtable table = new Hashtable();
table.put(key, value);
return table;
}
} // IntrospectionHelperTest